#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import asyncio
import socket
from PySide2.QtCore import QThread, Signal
from gglobal import logger, config
from .scan_car_network import scan_local_network, get_primary_local_network, get_local_ip_networks
from ..handlercore.connection_manager import ScanStateManager


class NetworkScanner(QThread):
    """网络扫描线程类"""
    
    # 定义信号
    device_found = Signal(str, str)  # IP地址, 设备名称
    scan_finished = Signal()
    
    def __init__(self, parent=None):
        super().__init__(parent)
        # 使用统一的扫描状态管理器
        self._scan_state_manager = ScanStateManager(self)
        self._network_range = None  # None表示自动检测
        self._ssh_user = "muyi"
        self._ssh_pass = "muyi@123"
        
    def start_scan(self, network_range=None, ssh_user="muyi", ssh_pass="muyi@123"):
        """开始扫描网络
        
        参数:
            network_range: 网络段，如 "192.168.1"。如果为None，则自动检测本机网段
            ssh_user: SSH用户名
            ssh_pass: SSH密码
        """
        self._network_range = network_range
        self._ssh_user = ssh_user
        self._ssh_pass = ssh_pass
        self._scan_state_manager.start_scan()
        self.start()
        
    def stop_scan(self):
        """停止扫描"""
        self._scan_state_manager.stop_scan()
        
    def run(self):
        """扫描线程主函数"""
        # 如果没有指定网络段，自动检测
        actual_network_range = self._network_range
        if actual_network_range is None:
            actual_network_range = get_primary_local_network()
            logger.info(f"自动检测到本机网段: {actual_network_range}")
        
        logger.info(f"开始扫描网络段: {actual_network_range}")
        
        loop = None
        try:
            # 创建新的事件循环
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            
            # 运行异步扫描 - 启用快速模式
            active_hosts, hosts_with_robot_id = loop.run_until_complete(
                scan_local_network(actual_network_range, self._ssh_user, self._ssh_pass, fast_mode=True)
            )
            # logger.debug(f"扫描结果{active_hosts}:{hosts_with_robot_id}")
            # 发射设备发现信号
            for robot_id, ip in hosts_with_robot_id:
                if self._scan_state_manager.is_scanning:
                    self.device_found.emit(ip, robot_id)
                    logger.debug(f"发现设备: {ip} - {robot_id}")
                else:
                    break
                    
            # 如果没有找到robot_id的设备，尝试发射普通设备
            if not hosts_with_robot_id:
                for host_info in active_hosts:
                    if not self._scan_state_manager.is_scanning:
                        break
                    if "Port 22 open" in host_info:
                        ip = host_info.split(" - ")[0].replace("IP: ", "")
                        device_name = f"{ip}"
                        self.device_found.emit(ip, device_name)
                        logger.debug(f"发现设备: {ip} - {device_name}")
                        
        except Exception as e:
            logger.error(f"网络扫描失败: {e}")
        finally:
            if loop is not None:
                try:
                    # 取消所有未完成的任务
                    pending_tasks = asyncio.all_tasks(loop)
                    for task in pending_tasks:
                        task.cancel()
                    
                    # 等待所有任务完成或取消
                    if pending_tasks:
                        loop.run_until_complete(asyncio.gather(*pending_tasks, return_exceptions=True))
                except Exception as cleanup_error:
                    logger.warning(f"清理事件循环时发生错误: {cleanup_error}")
                finally:
                    try:
                        loop.close()
                    except Exception as close_error:
                        logger.warning(f"关闭事件循环时发生错误: {close_error}")
            
        self._scan_state_manager.stop_scan()
        self.scan_finished.emit()
        logger.info("网络扫描完成")


class SimpleNetworkScanner(QThread):
    """简单网络扫描线程类（使用socket方式）"""
    
    # 定义信号
    device_found = Signal(str, str)  # IP地址, 设备名称
    scan_finished = Signal()
    
    def __init__(self, parent=None):
        super().__init__(parent)
        # 使用统一的扫描状态管理器
        self._scan_state_manager = ScanStateManager(self)
        
    def start_scan(self, network_range=None):
        """开始扫描网络
        
        参数:
            network_range: 网络段，如 "192.168.1"。如果为None，则自动检测本机网段
        """
        self._network_range = network_range
        self._scan_state_manager.start_scan()
        self.start()
        
    def stop_scan(self):
        """停止扫描"""
        self._scan_state_manager.stop_scan()
        
    def run(self):
        """扫描线程主函数"""
        # 如果没有指定网络段，自动检测
        actual_network_range = self._network_range
        if actual_network_range is None:
            actual_network_range = get_primary_local_network()
            logger.info(f"自动检测到本机网段: {actual_network_range}")
        
        logger.info(f"开始扫描网络段: {actual_network_range}")
        
        # 从配置获取SSH端口
        ssh_port = config.get_param('port', 22)
        
        # 扫描网络段 1-254
        for i in range(1, 255):
            if not self._scan_state_manager.is_scanning:
                break
                
            ip = f"{actual_network_range}.{i}"
            
            try:
                # 尝试连接SSH端口来检测设备 - 优化超时时间
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.settimeout(0.3)  # 减少超时时间以提高扫描速度
                result = sock.connect_ex((ip, ssh_port))  # 使用配置中的SSH端口
                sock.close()
                
                if result == 0:
                    # 尝试获取设备名称 - 添加超时控制
                    device_name = f"设备-{ip}"
                    try:
                        # 设置socket默认超时
                        original_timeout = socket.getdefaulttimeout()
                        socket.setdefaulttimeout(0.5)  # DNS查询超时
                        device_name = socket.gethostbyaddr(ip)[0]
                    except Exception:
                        device_name = f"设备-{ip}"
                    finally:
                        # 恢复原始超时设置
                        socket.setdefaulttimeout(original_timeout)
                        
                    self.device_found.emit(ip, device_name)
                    logger.debug(f"发现设备: {ip} - {device_name}")
                    
            except Exception as e:
                logger.debug(f"扫描 {ip} 失败: {e}")
                continue
                
        self._scan_state_manager.stop_scan()
        self.scan_finished.emit()
        logger.info("网络扫描完成")